﻿namespace Cik.Gapi4net.Testing.Service
{
    using System;
    using Gapi4Net.Core.AcsynRequest;
    using Gapi4Net.Core.FluentInterface;
    using Gapi4Net.Domain.Input;
    using Gapi4Net.Domain.Input.UrlBuilder;
    using Gapi4Net.Domain.Input.Validator;
    using Gapi4Net.Entlib.Logging;
    using Gapi4Net.Service.Contracts;
    using Gapi4Net.Service.Impls;
    using Gapi4Net.Testing;
    using JsonResultStubs;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;

    [TestClass]
    public class ServiceTesting : TestingBase
    {
        private IVideoSearchService _videoSearchService;
        private IBlogSearchService _blogSearchService;
        private IBookSearchService _bookSearchService;
        private IImageSearchService _imageSearchService;
        private ILocalSearchService _localSearchService;
        private INewsSearchService _newsSearchService;
        private IPatentSearchService _patentSearchService;
        private ITranslateService _translateService;
        private IWebSearchService _webSearchService;

        private Mock<ILoggerFactory> _loggerFactoryMock;
        private Mock<IDownloader> _downloaderMock;

        [TestInitialize]
        public override void InitTest()
        {
            base.InitTest();

            // mocking logger factory and downloader
            _loggerFactoryMock = new Mock<ILoggerFactory>();
            _downloaderMock = new Mock<IDownloader>();

            // mock logger instance
            _loggerFactoryMock.Setup(x => x.CreateLogger()).Returns(new LoggerWrapper());

            // create new service instances
            _blogSearchService = new BlogSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new BlogUrlBuilder(), new BlogValidator());
            _bookSearchService = new BookSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new BookUrlBuilder(), new BookValidator());
            _imageSearchService = new ImageSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new ImageUrlBuilder(), new ImageValidator());
            _localSearchService = new LocalSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new LocalUrlBuilder(), new LocalValidator());
            _newsSearchService = new NewsSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new NewsUrlBuilder(), new NewsValidator());
            _patentSearchService = new PatentSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new PatentUrlBuilder(), new PatentValidator());
            _translateService = new TranslateService(_loggerFactoryMock.Object, _downloaderMock.Object, new TranslateUrlBuilder(), new TranslateValidator());
            _videoSearchService = new VideoSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new VideoUrlBuilder(), new VideoValidator());
            _webSearchService = new WebSearchService(_loggerFactoryMock.Object, _downloaderMock.Object, new WebUrlBuilder(), new WebValidator());
        }

        [TestMethod]
        public void Can_Call_Search_From_Blog_Search_Service_Default()
        {
            _blogSearchService.Result = SearchStubs.GetJsonFromBlogSearchUrl();
            var result = _blogSearchService.Search("1.0", "Google");

            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Blog_Search_Service()
        {
            _blogSearchService.Result = SearchStubs.GetJsonFromBlogSearchUrl();

            var result = _blogSearchService.Search(() => Gapi4NetFactory<Blog>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .With(x => x.Start, 10)
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Book_Search_Service_Default()
        {
            _bookSearchService.Result = SearchStubs.GetJsonFromBookSearchUrl();
            var result = _bookSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Book_Search_Service()
        {
            _bookSearchService.Result = SearchStubs.GetJsonFromBookSearchUrl();

            var result = _bookSearchService.Search(() => Gapi4NetFactory<Book>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .With(x => x.Key, "key")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Image_Search_Service_Default()
        {
            _imageSearchService.Result = SearchStubs.GetJsonFromImageSearchUrl();
            var result = _imageSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Image_Search_Service()
        {
            _imageSearchService.Result = SearchStubs.GetJsonFromImageSearchUrl();
            var result = _imageSearchService.Search(() => Gapi4NetFactory<Image>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Local_Search_Service_Default()
        {
            _localSearchService.Result = SearchStubs.GetJsonFromLocalSearchUrl();
            var result = _localSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 1);
        }

        [TestMethod]
        public void Can_Call_Search_From_Local_Search_Service()
        {
            _localSearchService.Result = SearchStubs.GetJsonFromLocalSearchUrl();
            var result = _localSearchService.Search(() => Gapi4NetFactory<Local>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 1);
        }

        [TestMethod]
        public void Can_Call_Search_From_News_Search_Service_Default()
        {
            _newsSearchService.Result = SearchStubs.GetJsonFromNewsSearchUrl();
            var result = _newsSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_News_Search_Service()
        {
            _newsSearchService.Result = SearchStubs.GetJsonFromNewsSearchUrl();
            var result = _newsSearchService.Search(() => Gapi4NetFactory<News>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Patent_Search_Service_Default()
        {
            _patentSearchService.Result = SearchStubs.GetJsonFromPatentSearchUrl();
            var result = _patentSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Patent_Search_Service()
        {
            _patentSearchService.Result = SearchStubs.GetJsonFromPatentSearchUrl();
            var result = _patentSearchService.Search(() => Gapi4NetFactory<Patent>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Web_Search_Service_Default()
        {
            _webSearchService.Result = SearchStubs.GetJsonFromWebSearchUrl();
            var result = _webSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Web_Search_Service()
        {
            _webSearchService.Result = SearchStubs.GetJsonFromWebSearchUrl();
            var result = _webSearchService.Search(() => Gapi4NetFactory<Web>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        }

        [TestMethod]
        public void Can_Call_Search_From_Video_Search_Service_Default()
        {
            _videoSearchService.Result = SearchStubs.GetJsonFromVideoSearchUrl();
            var result = _videoSearchService.Search("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 1);
        }

        [TestMethod]
        public void Can_Call_Search_From_Video_Search_Service()
        {
            _videoSearchService.Result = SearchStubs.GetJsonFromVideoSearchUrl();
            var result = _videoSearchService.Search(() => Gapi4NetFactory<Video>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.MainResult.Length, 1);
        }

        [TestMethod]
        public void Can_Call_Detect_Language_From_Translate_Service_Default()
        {
            _translateService.Result = SearchStubs.GetJsonFromDetectLanguageUrl();
            var result = _translateService.DetectLanguage("1.0", "Google");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.Language, "en");
            Assert.AreEqual(result.ResponseData.IsReliable, false);
            Assert.AreEqual(result.ResponseData.Confidence, 0.11489271400000001);
        }

        [TestMethod]
        public void Can_Call_Detect_Language_From_Translate_Service()
        {
            _translateService.Result = SearchStubs.GetJsonFromDetectLanguageUrl();
            var result = _translateService.DetectLanguage(() => Gapi4NetFactory<Translate>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.Language, "en");
            Assert.AreEqual(result.ResponseData.IsReliable, false);
            Assert.AreEqual(result.ResponseData.Confidence, 0.11489271400000001);
        }

        [TestMethod]
        public void Can_Call_Translate_Language_From_Translate_Service_Default()
        {
            _translateService.Result = SearchStubs.GetJsonFromTranslateLanguageUrl();
            var result = _translateService.Translate("1.0", "hello world", "en|it");
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.TranslatedText, "ciao a tutti");
        }

        [TestMethod]
        public void Can_Call_Translate_Language_From_Translate_Service()
        {
            _translateService.Result = SearchStubs.GetJsonFromTranslateLanguageUrl();
            var result = _translateService.Translate(() => Gapi4NetFactory<Translate>
                                                             .Init()
                                                             .With(x => x.Version, "1.0")
                                                             .With(x => x.Query, "Google")
                                                             .With(x => x.LanguagePair, "en|it")
                                                             .Create());
            Assert.IsNotNull(result);
            Assert.IsTrue(result.ResponseStatus == 200);
            Assert.AreEqual(result.ResponseData.TranslatedText, "ciao a tutti");
        }

        #region real instance when we create new service

        //[TestMethod]
        //public void Can_Call_Search_From_Web_Search_Service()
        //{
        //    _webSearchService = new WebSearchService();
        //    var result = _webSearchService.Search("1.0", "Google");
        //    Assert.IsNotNull(result);
        //    Assert.IsTrue(result.ResponseStatus == 200);
        //    Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        //}

        //[TestMethod]
        //public void Can_Call_Search_From_Video_Search_Service()
        //{
        //    var result = _videoSearchService.Search("1.0", "Google");
        //    Assert.IsNotNull(result);
        //    Assert.IsTrue(result.ResponseStatus == 200);
        //    Assert.AreEqual(result.ResponseData.MainResult.Length, 4);
        //}

        //[TestMethod]
        //public void Can_Call_Detect_Language_From_Translate_Service()
        //{
        //    var result = _translateService.DetectLanguage("1.0", "Google");
        //    Assert.IsNotNull(result);
        //    Assert.IsTrue(result.ResponseStatus == 200);
        //    Assert.AreEqual(result.ResponseData.Language, "en");
        //    Assert.AreEqual(result.ResponseData.IsReliable, false);
        //    Assert.AreEqual(result.ResponseData.Confidence, 0.0);
        //}

        //[TestMethod]
        //public void Can_Call_Translate_Language_From_Translate_Service()
        //{
        //    var result = _translateService.Translate("1.0", "hello world", "en|it");
        //    Assert.IsNotNull(result);
        //    Assert.IsTrue(result.ResponseStatus == 200);
        //    Assert.AreEqual(result.ResponseData.TranslatedText, "ciao a tutti");
        //}

        #endregion real instance when we create new service

        [TestCleanup]
        public override void EndTest()
        {
            base.EndTest();

            #region release memory

            if (_blogSearchService != null)
                GC.SuppressFinalize(_blogSearchService);
            if (_bookSearchService != null)
                GC.SuppressFinalize(_bookSearchService);
            if (_imageSearchService != null)
                GC.SuppressFinalize(_imageSearchService);
            if (_localSearchService != null)
                GC.SuppressFinalize(_localSearchService);
            if (_newsSearchService != null)
                GC.SuppressFinalize(_newsSearchService);
            if (_patentSearchService != null)
                GC.SuppressFinalize(_patentSearchService);
            if (_translateService != null)
                GC.SuppressFinalize(_translateService);
            if (_videoSearchService != null)
                GC.SuppressFinalize(_videoSearchService);
            if (_webSearchService != null)
                GC.SuppressFinalize(_webSearchService);

            #endregion release memory
        }
    }
}